package com.wu.family.utils.img;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.ref.WeakReference;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.wu.family.utils.ze.LoadBitmapMgr;


import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.ImageView;

public abstract class AbsBitmapMgr implements IBitmapMgr {
	public final static String OLD_CACHE_PATH = Environment.getExternalStorageDirectory()
			+ "/family/pic_cache/";
	public final static String PIC_CACHE_PATH = Environment.getExternalStorageDirectory() 
			+ "/family/.picCache/";
	public static Map<String, WeakReference<Bitmap>> imageCache = new HashMap<String, WeakReference<Bitmap>>();
	
	public AbsBitmapMgr() {
		File oldDir = new File(OLD_CACHE_PATH);
		File dir = new File(PIC_CACHE_PATH);
		if (oldDir.exists()) {
			oldDir.renameTo(dir);
		}else if ( !dir.exists()) {
			dir.mkdirs();
		}
	}
	
	public String addImageCache(Bitmap bitmap, String imageUrl) {
		FileOutputStream outputStream = null;
		ObjectOutputStream	objectOutputStream = null ;
		String localUrl = "";
		try {
			if(bitmap != null) {
				imageCache.put(imageUrl, new WeakReference<Bitmap>(bitmap));
				localUrl = PIC_CACHE_PATH + formatString( imageUrl );
				File bitmapFile = new File(localUrl);
				if (bitmapFile.exists()) {
					bitmapFile.delete();
				}
				bitmapFile.createNewFile();
				outputStream = new FileOutputStream(bitmapFile);
				objectOutputStream = new ObjectOutputStream(outputStream);
				objectOutputStream.writeObject( bitmap2ByteArray(bitmap) );
			
				objectOutputStream.flush();
				objectOutputStream.close();
				outputStream.close();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return localUrl;
	}
	
	public void removeImageCache(String urlString) {
		if (imageCache.containsKey(urlString)) {
			imageCache.remove(urlString);
		}
		File cacheFile = new File( PIC_CACHE_PATH + formatString( urlString ) );
		if ( cacheFile.exists() ) {
			cacheFile.delete();
		}
	}
	
	public Bitmap getImageCache(String imageUrl) {
		if (imageCache.containsKey(imageUrl)) {
            WeakReference<Bitmap> softReference = imageCache.get(imageUrl);
            Bitmap bitmap = softReference != null ? softReference.get() : null;
	            
            return bitmap;
		}
		return null;
	}
	
	public void deleteSDcardBugCache() {
		File dir = new File(PIC_CACHE_PATH);
		if (dir.exists()) {
			File[] Files = dir.listFiles();
			if (Files != null && Files.length > 0) {
				for (File file : Files) {
					if (file.isFile() && !file.getAbsolutePath().contains("!")) {
						file.delete();
					}
				}
			}
		}
	}
	
	public void renameAllCache() {
		File dir = new File(PIC_CACHE_PATH);
		if (dir.exists()) {
			File[] Files = dir.listFiles();
			if (Files != null && Files.length > 0) {
				for (File file : Files) {
					String path = file.getAbsolutePath();
					if (file.isFile() && path.matches(".*\\.(jpg|jpeg|png).*")) {
						File newFile = new File(path.replaceAll("\\.(jpg|jpeg)", "\\.img")
								.replaceAll("\\.png", "\\.pimg"));
						file.renameTo(newFile);
					}
				}
			}
		}
	}
	
	public Bitmap loadBitmap(final String imageUrl, final ImageView view ,ImageCallBack customCallBack) {
		final ImageCallBack callBack;
		if (customCallBack != null) {
			callBack = customCallBack;
		}else {
			callBack = defaultCallBack;
		}
		final Handler  handler =  new Handler() {
			public void handleMessage(Message msg) {
				if( msg.what == 0 ) {
					if((Bitmap) msg.obj != null) {
						imageCache.put(imageUrl, new WeakReference<Bitmap>((Bitmap) msg.obj));
					}
					callBack.setImage((Bitmap) msg.obj, imageUrl, view);
				}else if( msg.what == 1 ) {
					if ( msg.obj == null ) {
						netLoadImage(imageUrl, this);
					}else {
						imageCache.put(imageUrl, new WeakReference<Bitmap>((Bitmap) msg.obj));
						callBack.setImage((Bitmap) msg.obj, imageUrl, view);
					}
				}
				
			}; 
		 };
		 
		view.setTag(imageUrl);
		Bitmap bitmap = null;
		 if (imageCache.containsKey(imageUrl)) {
	            WeakReference<Bitmap> softReference = imageCache.get(imageUrl);
	            bitmap = softReference != null ? softReference.get() : null;
	            if ( null == bitmap ) {
	            	imageCache.remove(imageUrl);
	            	loadBitmap(imageUrl,view,callBack);
				}else {
					callBack.setImage(bitmap, imageUrl, view);
		            return bitmap;
				}
		 }else {
			findLocalImage(imageUrl, handler); 
		 }
		 callBack.setImage(bitmap, imageUrl, view);
		 return null;
	}
	
	public Bitmap loadBitmap2(final String imageUrl, final ImageView view ,ImageCallBack customCallBack) {
		final ImageCallBack callBack;
		if (customCallBack != null) {
			callBack = customCallBack;
		}else {
			callBack = defaultCallBack;
		}
		final Handler  handler =  new Handler() {
			public void handleMessage(Message msg) {
				if( msg.what == 0 ) {
					if((Bitmap) msg.obj != null) {
						LocalBitmapMgr.getInstance().addBitmap(imageUrl, (Bitmap) msg.obj);
					}
					callBack.setImage((Bitmap) msg.obj, imageUrl, view);
				}else if( msg.what == 1 ) {
					if ( msg.obj == null ) {
						netLoadImage(imageUrl, this);
					}else {
						LocalBitmapMgr.getInstance().addBitmap(imageUrl, (Bitmap) msg.obj);
						callBack.setImage((Bitmap) msg.obj, imageUrl, view);
					}
				}
				
			}; 
		 };
		 
		view.setTag(imageUrl);
		Bitmap bitmap = LocalBitmapMgr.getInstance().getBitmap(imageUrl) ;
		if (bitmap != null) {
			if (!bitmap.isRecycled()) {
				callBack.setImage(bitmap, imageUrl, view);
				return bitmap;
			}else {
				LocalBitmapMgr.getInstance().removeKey(imageUrl);
			}
		}else {
			findLocalImage(imageUrl, handler);
		}
		callBack.setImage(bitmap, imageUrl, view);
		return null;
	}
	
	public void findLocalImage(final String imageUrl,final Handler handler) {
		findLocalBackground(new Runnable() {
			
			@Override
			public void run() {
				Bitmap bitmap = null;
				FileInputStream inputStream = null;
				ObjectInputStream objectInputStream = null;
				try {
					File cacheFile = new File( PIC_CACHE_PATH + formatString( imageUrl ) );
					if ( cacheFile.exists() ) {
						inputStream = new FileInputStream(cacheFile);
						objectInputStream = new ObjectInputStream(inputStream);
						byte[] buffer = (byte[]) objectInputStream.readObject();
						bitmap = ByteArray2Bitmap( buffer);
					}
					handler.sendMessage(handler.obtainMessage(1, bitmap));
					
				} catch (EOFException e) {
					Log.d("EOFExcep imgUrl", imageUrl);
					File cacheFile = new File( PIC_CACHE_PATH + formatString( imageUrl ) );
					if ( cacheFile.exists() ) {
						cacheFile.delete();
					}
					e.printStackTrace();
				}catch (Exception e) {
					e.printStackTrace();
				} finally {
					try {
						if (inputStream != null ) {
							inputStream.close();
							inputStream = null;
						}
						if (objectInputStream != null ) {
							objectInputStream.close();
							objectInputStream = null;
						}
					} catch (Exception e2) { 
						e2.printStackTrace();
					}
				}
			}
		});
	}
	
	public void netLoadImage(final String imageUrl,final Handler handler) {
		netLoadBackground(new Runnable() {
			
			@Override 
			public void run() {
				Bitmap bitmap = null;
				FileOutputStream outputStream = null;
				ObjectOutputStream	objectOutputStream = null ;
				try {
					HttpURLConnection conn = (HttpURLConnection)new URL(imageUrl).openConnection();
					conn.setConnectTimeout(8 * 1000); 
					conn.setRequestMethod("GET");
					if(conn.getResponseCode()==200){
						BitmapFactory.Options options = new BitmapFactory.Options(); 
						options.inJustDecodeBounds = false;
						options.inSampleSize = 1;
						options.inPreferredConfig = Bitmap.Config.RGB_565;
						options.inPurgeable = true;
						options.inInputShareable = true;
						
						BufferedInputStream buf = new BufferedInputStream(conn.getInputStream());
						bitmap = BitmapFactory.decodeStream(buf, null, options);
					}
					
					//Drawable.createFromStream(new URL(imageUrl).openStream(), "png");
					if(bitmap != null) {
						handler.sendMessage(handler.obtainMessage(0, bitmap));
						File bitmapFile = new File(PIC_CACHE_PATH + formatString( imageUrl ));
						if (bitmapFile.exists()) {
							bitmapFile.delete();
						}
						bitmapFile.createNewFile();
						outputStream = new FileOutputStream(bitmapFile);
						objectOutputStream = new ObjectOutputStream(outputStream);
						objectOutputStream.writeObject( bitmap2ByteArray(bitmap) );
					
						objectOutputStream.flush();
						objectOutputStream.close();
						outputStream.close();
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			
			}
		});
	}
	
	public byte[] bitmap2ByteArray(final Bitmap bitmap) {
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		bitmap.compress(CompressFormat.JPEG, 100, baos);
		byte[] bitmapArray = baos.toByteArray();
		try {
			baos.close();
			baos = null;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return bitmapArray;
	}
	
	public Bitmap ByteArray2Bitmap(byte[] bitmapArray) {
		BitmapFactory.Options options = new BitmapFactory.Options(); 
		options.inJustDecodeBounds = false;
		options.inSampleSize = 1;
		options.inPreferredConfig = Bitmap.Config.RGB_565;
		options.inPurgeable = true;
		options.inInputShareable = true;
		Bitmap bitmap = BitmapFactory.decodeByteArray(bitmapArray, 0, bitmapArray.length, options);
		return bitmap;
	}
	
	public ImageCallBack defaultCallBack = new ImageCallBack() {
		
		@Override
		public void setImage(Bitmap bmp, String url, ImageView view) {
			if(url.equals((String)view.getTag())) {
				view.setImageBitmap(bmp);
			}
		}
	};
	
	public String formatString( final String from ) {
		//return MD5.MD5Encode(from)+ ((from.lastIndexOf(".")!=-1)?from.substring(from.lastIndexOf(".")):".jpg");
		String formatStr = new String(from);
		String[] strs = formatStr.split("/");
		
		formatStr = "";
		for( int i=0; i<strs.length; i++ ) {
			formatStr = formatStr + strs[i];
		}
		int index = formatStr.lastIndexOf("com");
		formatStr = formatStr.substring(index!=-1?index:0);
		//formatStr = formatStr.contains("!")?formatStr:(formatStr+"!600");
		formatStr = formatStr.replaceAll("\\.(jpg|jpeg)", "\\.img").replaceAll("\\.png", "\\.pimg");
		
		return formatStr;
	}
	
	public interface ImageCallBack {
		public void setImage(Bitmap bmp,String url, ImageView view);
	}
	
	public void recycle(List<String> photoUrl) {
		if (photoUrl == null) {
			return;
		}
		for (int i = 0; i < photoUrl.size(); i++) {
			String url = photoUrl.get(i);
			if (imageCache.containsKey(url)) {
				WeakReference<Bitmap> softReference = imageCache.get(url);
	            Bitmap bitmap = softReference != null ? softReference.get() : null;
				if (bitmap != null && !bitmap.isRecycled()) {
					bitmap.recycle();
					bitmap = null;
				}
				imageCache.remove(url);
			}
		}
	}
}